package org.ponly.lpf4j.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.zip.ZipFile;

/**
 */
public abstract class Utils {
    public static final String SYSTEM_NAME;
    public static final String SYSTEM_VERSION;

    static {
        String name = "LPF4J";
        String version = "(UNKNOWN)";
        InputStream in = Utils.class.getClassLoader().getResourceAsStream("META-INF/maven/org.ponly/ponly-lpf4j/pom.properties");
        if (null != in) {
            try {
                try {
                    Properties props = new Properties();
                    props.load(in);
                    name = props.getProperty("artifactId", name).toUpperCase();
                    version = props.getProperty("version", version);
                } finally {
                    in.close();
                }
            } catch (Exception ignore) {
                // ignore
            }
        }
        SYSTEM_NAME = name;
        SYSTEM_VERSION = version;
    }

    public static String join(final String[] strings, final String separator) {
        return join(strings, 0, strings.length, separator);
    }

    public static String join(final List<String> strings, final String separator) {
        return join(strings, 0, strings.size(), separator);
    }

    public static String join(final String[] strings, int startIndex, int endIndex, final String separator) {
        return join(Arrays.asList(strings), startIndex, endIndex, separator);
    }

    public static String join(final List<String> strings, int startIndex, int endIndex, final String separator) {
        final StringBuilder result = new StringBuilder();
        for (int i = startIndex; i < endIndex; i++) {
            if (i > startIndex) {
                result.append(separator);
            }
            result.append(strings.get(i));
        }
        return result.toString();
    }

    public static boolean endsWithIgnoreCase(String str, String suffix) {
        final int stringLength = str.length();
        final int suffixLength = suffix.length();
        return stringLength >= suffixLength && str.regionMatches(true, stringLength - suffixLength, suffix, 0, suffixLength);
    }

    /**
     * 是否是需要解压安装的插件
     *
     * @param f
     * @return
     */
    public static boolean isUnarchiveFile(final File f) {
        if (f.exists() && isJarOrZip(f)) {
            try {
                ZipFile zipFile = new ZipFile(f);
                try {
                    return null != zipFile.getEntry("lib/") || null != zipFile.getEntry("classes/");
                } finally {
                    zipFile.close();
                }
            } catch (IOException e) {
                // ignore
            }
        }
        return false;
    }

    public static boolean isJarOrZip(File file) {
        if (file.isDirectory()) {
            return false;
        }
        final String name = file.getName();
        return endsWithIgnoreCase(name, ".jar") || endsWithIgnoreCase(name, ".zip");
    }

    public static String getFileName(String path) {
        if (path.length() == 0) {
            return "";
        }
        final char c = path.charAt(path.length() - 1);
        int end = c == '/' || c == '\\' ? path.length() - 1 : path.length();
        int start = Math.max(path.lastIndexOf('/', end - 1), path.lastIndexOf('\\', end - 1)) + 1;
        return path.substring(start, end);
    }

    public static int compareVersionNumbers(String v1, String v2) {
        if (v1 == null && v2 == null) {
            return 0;
        } else if (v1 == null) {
            return -1;
        } else if (v2 == null) return 1;

        String[] part1 = v1.split("[\\.\\_\\-]");
        String[] part2 = v2.split("[\\.\\_\\-]");

        int idx = 0;
        for (; idx < part1.length && idx < part2.length; idx++) {
            String p1 = part1[idx];
            String p2 = part2[idx];

            int cmp;
            if (p1.matches("\\d+") && p2.matches("\\d+")) {
                cmp = new Integer(p1).compareTo(new Integer(p2));
            } else {
                cmp = part1[idx].compareTo(part2[idx]);
            }
            if (cmp != 0) return cmp;
        }

        if (part1.length == part2.length) {
            return 0;
        } else if (part1.length > idx) {
            return 1;
        } else {
            return -1;
        }
    }

    public static void clearJarUrlCache() {
        try {
            Class<?> factory = Class.forName("sun.net.www.protocol.jar.JarFileFactory");
            clearMap(factory.getDeclaredField("fileCache"));
            clearMap(factory.getDeclaredField("urlCache"));
        } catch (Exception e) {
            // ignore
        }
    }

    private static void clearMap(Field cache) throws IllegalAccessException {
        cache.setAccessible(true);
        if ((cache.getModifiers() & Modifier.FINAL) == 0) {
            cache.set(null, new HashMap());
        } else {
            Map<?, ?> map = (Map<?, ?>) cache.get(null);
            map.clear();
        }
    }
}
